package com.nlp.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import com.carrotsearch.labs.langid.DetectedLanguage;
import com.carrotsearch.labs.langid.ILangIdClassifier;
import com.carrotsearch.labs.langid.LangIdV3;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hankcs.hanlp.HanLP;
import com.nlp.utils.SummaryTask;
import com.nlp.utils.SummaryUtils;

@Service
public class SummaryServiceImpl implements SummaryService {

	private static String isSimpleOrComplex(String str) {
        try {
            if (str.equals(new String(str.getBytes("gb2312"), "gb2312"))) {
               return "simple";
            }else{
                return "complex";
            }
        } catch (Exception e) {
        	return null;
        }
	}

	
	/*private static void isChinneseOrEnglish(String str) {
        String reg = "[\\u4E00-\\u9FA5]+";
        Matcher m = Pattern.compile(reg).matcher(str);
        if (m.find()) {
            System.out.println(str + "---是中文");
            return;
        }
        System.out.println(str + "---是英文");
    }*/
	
	
	public String getSummaryText(String secretkey, 
			String secretkid, String content, String ratio) {
		try {
			content = content.substring(0, content.length() > 8100 ? 8100 : content.length());
//			content = content.substring(0, content.length() > 10000 ? 10000 : content.length());
			
			String sc = isSimpleOrComplex(content);
			
			if("complex".equals(sc)) {
				content = HanLP.convertToSimplifiedChinese(content);
			}
			
			
			ILangIdClassifier langIdClassifier = new LangIdV3();
			DetectedLanguage classify = langIdClassifier.classify(content, false);
			String language = classify.getLangCode();
			
			if(StringUtils.isBlank(language)) {
				language = "en";
			}
			
			/**
			 * 加入分词繁简体判断			
			 */

			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new Date());
			long timeInMillis = calendar.getTimeInMillis();
			String summary = SummaryUtils.getSummary("getSummary", content, language, "bj", secretkid,
					String.valueOf(timeInMillis), "1.0", secretkey, ratio);

			return summary;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "发生错误";
	}
	
	
	
	public String getSummary(String language, String secretkey, 
			String secretkid, InputStream fis, String fileName, String ratio) {
		try {
			String content = SummaryUtils.extractText(fis, fileName);
			content = content.substring(0, content.length() > 8100 ? 8100 : content.length());
//			content = content.substring(0, content.length() > 10000 ? 10000 : content.length());
			
			content = content.replaceAll("[\\n]", "");
			
			ILangIdClassifier langIdClassifier = new LangIdV3();
			DetectedLanguage classify = langIdClassifier.classify(content, false);
			language = classify.getLangCode();
			
			if(StringUtils.isBlank(language)) {
				language = "en";
			}
			
			if("zh".equals(language)) {
				String sc = isSimpleOrComplex(content);
				if("complex".equals(sc)) {
					content = HanLP.convertToSimplifiedChinese(content);
				}
			}

			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new Date());
			long timeInMillis = calendar.getTimeInMillis();
			String summary = SummaryUtils.getSummary("getSummary", content, language, "bj", secretkid,
					String.valueOf(timeInMillis), "1.0", secretkey, ratio);
			
			/*summary = summary.replaceAll("#_#","\\\n");*/
			
			return summary;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "发生错误";
	}


	public Map<String, Map<String, String>> getHtmlSummary(/* InputStream fis , */String language, String secretkey,
			String secretkid, String uri) {
//		List<String> list = Arrays.asList("new","new1","new3","new4","old","old1","old2","old3","old4","old5","old6","old7","old8");
//		for (String name : list) {
//			System.out.println("-----------------------------"+name+"-----------------------------");

		long start = System.currentTimeMillis();
		System.out.println(start+"这里开始");
		Connection connect = Jsoup.connect(uri);
		connect.maxBodySize(0);
		connect.timeout(200000);

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		long timeInMillis = calendar.getTimeInMillis();
		try {



			Document doc = connect.get();
			System.out.println("get html time is:" + (System.currentTimeMillis() - start) + "ms");
//			doc.select("text > table").remove();
			Elements pEles = doc.select("text > p");
			Elements divEles = new Elements();






			if (!pEles.isEmpty()) {
				divEles = pEles;

			} else {
				divEles = doc.getElementsByTag("div");

			}

			String tmp;
			Element tbody = null;
			List<Element> tdList = doc.getElementsByTag("td");

			List<Element> trList = Lists.newArrayList();
			if (!divEles.isEmpty()) {


				for (Element divEle : tdList) {
					tmp = divEle.text();
					System.out.println(tdList+"什么内容");
					if (!StringUtils.isBlank(tmp) && tmp.toLowerCase().endsWith("business")) {
						tbody = divEle.parent().parent();
						trList = tbody.getElementsByTag("tr");
						break;
					}
				}
			}

			List<Integer> indexs = Lists.newArrayList();
			ArrayList<Element> tmpList = Lists.newArrayList();
			Element page = null;
			if (!trList.isEmpty()) {
				Element tr;
				Elements as;
				for (int i = 0; i < trList.size(); i++) {
					tr = trList.get(i);
					tmp = tr.text();
					if (tmp.toLowerCase().startsWith("part")) {
						continue;
					}
					if (StringUtils.isBlank(tmp)) {
						tmpList.add(tr);
						continue;
					}
					tdList = tr.getElementsByTag("td");
					if (tdList.size() > 0) {
						page = tdList.get(tdList.size() - 1);
						tmp = page.text();
						if (StringUtils.isNumeric(tmp)) {
							continue;
						}
					}
					tmpList.add(tr);

//					if (!StringUtils.isBlank(tmp) && tmp.toLowerCase().startsWith("item")) {
//						if(null!=tdd&&tdd.parent().childNodeSize()>2) {
//							tmpList.add(tdd);
//							continue;
//						}
//					}
//					if (!StringUtils.isBlank(tmp) && StringUtils.isNumeric(tmp)) {
//						tmpList.add(tdd);
//						continue;
//					}
//					if (StringUtils.isBlank(tmp)) {
//						tmpList.add(tdd);
//						continue;
//					}
//					as = tdd.select("a");
//					if(as.isEmpty()&&!tmp.toLowerCase().startsWith("part")) {
//						tmpList.add(tdd);
//					}
				}

				trList.removeAll(tmpList);
				for (Element trele : trList) {
					tmp = trele.text();
					if (!StringUtils.isBlank(tmp) && tmp.toLowerCase().startsWith("part")) {
						indexs.add(trList.indexOf(trele));
					}
				}
			}

			List<String> hyperlinkList = Lists.newArrayList();
			String lastHyperlink = null;
			Map<String, Map<String, String>> partMap = Maps.newLinkedHashMap();
			Integer partNum = 1;
			String tmpKey = null;
			Node aNode = null;
			String href = null;
			Map<String, String> itemMap = null;
			if (!indexs.isEmpty()) {
				for (int i = indexs.get(0); i < trList.size(); i++) {
					tmp = trList.get(i).text();
					if (!StringUtils.isBlank(tmp) && tmp.toLowerCase().startsWith("part")) {
						if (null != itemMap && !itemMap.isEmpty()) {
							partMap.put(tmpKey, itemMap);
						}
						itemMap = Maps.newLinkedHashMap();
						tmpKey = "Part" + SummaryUtils.intToRoman(partNum++);
						continue;
					}
//					if (null != itemMap&&!itemMap.isEmpty()) {
//					String text = tdList.get(i).text();
					if (!StringUtils.isBlank(tmp)) {
//						System.out.println(tmp);
						aNode = trList.get(i).select("a").get(0);
						if (null != aNode) {
							href = aNode.attr("href").replaceFirst("#", "");
							hyperlinkList.add(href);
						}
						itemMap.put(href, /* "part" + (partNum - 1) + "." + */tmp);
						if (i == trList.size() - 1) {
							lastHyperlink = href;
							partMap.put(tmpKey, itemMap);
						}
					}
//					}
				}
			}

			if (null != tbody) {
				tbody.remove();
			}
			List<Element> divList = Lists.newArrayList();
			if (!pEles.isEmpty()) {
				divList = doc.getElementsByTag("p");
			} else {
				divList = doc.getElementsByTag("div");
			}
			List<String> indexList = Lists.newArrayList();
			Integer tmpIdx;
			String tmpName;
			Element tmpDivEle;
			Elements tmpAEles;
			for (int i = 0; i < divList.size(); i++) {
				tmpDivEle = divList.get(i);
				tmpAEles = tmpDivEle.getElementsByTag("a");
				if (tmpAEles.size() > 0) {
					tmpIdx = divList.indexOf(tmpDivEle);
					tmpName = tmpAEles.get(0).attr("name");
					if (hyperlinkList.contains(tmpName)) {
						indexList.add(tmpName + "|" + tmpIdx);
					}
				}
			}

			int lastHyperlinkIndex = 0;
			if (!indexList.isEmpty() && null != lastHyperlink) {
				Collections.sort(indexList, new Comparator<String>() {


					public int compare(String o1, String o2) {
						o1 = o1.substring(o1.indexOf("|") + 1);
						o2 = o1.substring(o1.indexOf("|") + 1);
						if (StringUtils.isNumeric(o1) && StringUtils.isNumeric(o2)) {
							int int1 = Integer.parseInt(o1);
							int int2 = Integer.parseInt(o2);
							if (int1 > int2) {
								return -1;

							}
							if (int1 < int2) {
								return 1;

							}
							if (int1 == int2) {
								return 0;
							}
						}
						return 0;
					}
				});
				for (String index : indexList) {
					if (index.startsWith(lastHyperlink)) {
						lastHyperlinkIndex = indexList.indexOf(index);
					}
				}
			}
			if (lastHyperlinkIndex != 0) {
				indexList = indexList.subList(0, lastHyperlinkIndex + 1);
			}

			List<String> newIndexs = Lists.newArrayList();
			for (String index : indexList) {
				if (!index.startsWith("|")) {
					newIndexs.add(index);
				}
			}

			ConcurrentMap<String, String> returnMap = new ConcurrentHashMap<String, String>();
//			Map<String, String> summaryMap = Maps.newLinkedHashMap();
			Set<Entry<String, Map<String, String>>> partSet = partMap.entrySet();
			Iterator<Entry<String, Map<String, String>>> partIt = partSet.iterator();
			String hyperlink;
			int fromIndex;
			int toIndex;
			int count = 0;
			StringBuffer buffer = new StringBuffer();
			String query;
			List<Element> subList = Lists.newArrayList();
			String itemKey = "";
			String itemValue = "";
			Map<String, String> itemMapTmp;
			Entry<String, Map<String, String>> partEntry;
			Set<Entry<String, String>> itemSet;
			Iterator<Entry<String, String>> itemIt;
			Entry<String, String> itemEntry;
//			String res = "";
			ExecutorService pool = Executors.newFixedThreadPool(20);
			while (partIt.hasNext()) {
				partEntry = partIt.next();
				itemMapTmp = partEntry.getValue();
				itemSet = itemMapTmp.entrySet();
				itemIt = itemSet.iterator();
//				summaryMap = Maps.newLinkedHashMap();
				while (itemIt.hasNext()) {
					itemEntry = itemIt.next();
					itemKey = itemEntry.getKey();
					itemValue = itemEntry.getValue();
					if (!StringUtils.isBlank(itemKey) && !StringUtils.isBlank(itemValue)) {
						hyperlink = newIndexs.get(count);
						if (hyperlink.startsWith(itemKey)) {
							fromIndex = Integer.parseInt(hyperlink.substring(hyperlink.indexOf("|") + 1));
							if (count == newIndexs.size() - 1) {
								toIndex = divList.size() - 1;
							} else {
								hyperlink = newIndexs.get(++count);
								toIndex = Integer.parseInt(hyperlink.substring(hyperlink.indexOf("|") + 1)) - 1;
							}
							subList = divList.subList(fromIndex, toIndex);

							for (Element ele : subList) {
								buffer.append(ele.text().trim()/*+"\\n"*/);
							}
							query = buffer.toString();
							query = query.substring(0, query.length() > 8000 ? 8000 : query.length());
							buffer.delete(0, buffer.length());
							start = System.currentTimeMillis();
							SummaryTask summaryTask = new SummaryTask(returnMap, "getSummary", query, language, "bj",
									secretkid, String.valueOf(timeInMillis), "1.0", secretkey, partEntry.getKey(),
									itemValue);
//							res = SummaryUtils.getSummary("getSummary", query, language, "bj", secretkid,
//									String.valueOf(timeInMillis), "1.0", secretkey);
							pool.submit(summaryTask);
//							summaryMap.put(itemValue, res);

						}
					}

				}
//				returnMap.put(partEntry.getKey(), summaryMap);
			}
			pool.shutdown();
			while (true) {
				if (pool.isTerminated()) {
					System.out.println("所有的子线程都结束了！");
					break;
				}
				Thread.sleep(1000);
			}

			Map<String, Map<String, String>> retMap = Maps.newLinkedHashMap();
			Map<String, String> summaryMap;
			Set<String> keys = partMap.keySet();
			Set<String> itemKeys;
			Set<String> returnKeys = returnMap.keySet();
			String returnItemKey;
			String returnItemVal;
			for (String key : keys) {
				summaryMap = partMap.get(key);
				itemKeys = summaryMap.keySet();
				Map<String, String> returnSummaryMap = Maps.newLinkedHashMap();
				for (String itemKey2 : itemKeys) {
					for (String returnKey : returnKeys) {
						if ((key+"|"+summaryMap.get(itemKey2)).equals(returnKey)) {						
							returnItemKey = returnKey.substring(returnKey.indexOf("|") + 1);
							returnItemVal = returnMap.get(returnKey);
							returnSummaryMap.put(returnItemKey, returnItemVal);
						}

					}
				}
				retMap.put(key, returnSummaryMap);
			}

			System.out.println(count + "-------get html summary time is:"
					+ (System.currentTimeMillis() - start) + "ms");
			return retMap;
		} catch (Exception e) {
			e.printStackTrace();
		}

//		}
		return null;
	}

}
